/**
 * 它实现的是为 PNG 文件中的 Chunk 计算 CRC32 校验值的逻辑，符合 PNG 的官方规范。
 */


// Initialize CRC Table
// 预先生成一个 CRC32 查找表（256 个值），便于高效查表计算，而不是每次都重复计算多项式。
const CRC_TABLE = createCrcTable();

/**
 * Create the initial CRC table needed to calculate the checksums.
 *
 * @return {number[]} An array containing hashes.
 */
function createCrcTable() {
  // 初始化一个空数组，用于存放 256 个 CRC 预计算结果。
  const crcTable = [];

  // 这是 CRC 的位移和多项式运算核心逻辑：
  for (let n = 0; n < 256; n += 1) {
    // 对每个字节 n，逐位计算 CRC；
    let c = n;
    for (let k = 0; k < 8; k += 1) {
      // 如果最低位是 1，则异或一个常量 0xEDB88320（这是 PNG 使用的 CRC32 逆多项式）；
      // 否则直接右移一位；
      // 连续操作 8 次，完成整个字节的 CRC 转换。

      c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
    }
    crcTable[n] = c;
  }

  // 最终将计算好的值存入数组，并返回整张查表。
  return crcTable;
}

/**
 * 按照 PNG 规范计算 chunk 的 CRC 校验码，用于生成或校验 PNG 文件的正确性
 * Calculates a CRC32 checksum of a PNG chunk.
 *
 * @param {string} chunkName The name of the chunk to calculate the CRC for. PNG 块的 4 字节类型名，例如 "IDAT"、"IHDR"；
 * @param {ArrayBuffer} chunkData The data to calculate the CRC for. 这个块的数据内容部分（不含长度、类型、CRC）。
 * @return {number} The calculated CRC checksum.
 */
function crc32(chunkName, chunkData) {
  const uint8Array = new Uint8Array(chunkData.byteLength + 4);
  uint8Array.set(chunkName.split('').map(str => str.charCodeAt(0)), 0);
  uint8Array.set(new Uint8Array(chunkData), 4);

  let crc = 0 ^ (-1);

  for (const byte of uint8Array) {
    crc = (crc >>> 8) ^ CRC_TABLE[(crc ^ byte) & 0xFF];
  }

  return (crc ^ (-1)) >>> 0;
}